perm filename NOTES.PRJ[LSP,JRA] blob sn#316175 filedate 1977-11-09 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00004 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	.SEC(Projects)
C00010 00003	.SS(Pretty-printing,,P226:)
C00020 00004	.REQUIRE "NOTES.SDP" SOURCE_FILE
C00034 ENDMK
C⊗;
.SEC(Projects)
.FP
This chapter consists of a set of non-trivial projects which either apply LISP 
or extend LISP by adding new language features.
.SS(Extensions to %3eval%*,%3eval%*,P67:)
.SELECT 1;


.BEGIN TURN ON "#";
This first  project was derived from the syntax of 
⊗→MUDDLE↔← ⊗↑[Mud#75]↑, ⊗→CONNIVER↔← ⊗↑[Con#73]↑, and
⊗→MICRO-PLANNER↔← ⊗↑[Mic#71]↑.

We have seen that LISP calling sequences are of two varieties: either
evaluate %6all%* of the arguments; or  evaluate %6none%* of the
arguments.
To generalize this regime we might allow the evaluation of some selection
of the actual parameters; the formal parameter list could specify which
parameters are to be evaluated.
We have also specified that the number of formal parameters
must agree with the number of actual parameters; yet 
it is sometimes useful in practice to allow such a discrepancy. Some
implementations allow a mis-match, supplying default values when too
few are given, and discarding the excess  actual parameters after their
evaluation.
We might partition the formal parameters into required parameters, optional 
parameters, and an excess collector to handle any actual parameters left over.
Required parameters %6must%* have corresponding actual parameters; optional
actual parameters are used if present, otherwise  default 
values are used.
If there are more actual parameters than the formals encompassed by the first
two classes, then they are associated with the excess collector.

.GROUP;
To be more precise consider the following possible BNF equations:

.BEGIN TABIT1(15);TURN OFF "←";
.BOXA
<varlist>\::=[<required> <optional> <excess>]
.PT2
<required>\::= <par>; ...;<par> | %9ε%* ⊗↓The symbol "%9ε%1" stands for the empty string.←
.PT2
<optional>\::= "optional" <opn>; ...; <opn> | %9ε%*
.PT2
<excess>\::= "excess" <par> | %9ε%*
.PT2
<par>\::= <variable> | %9`%*<variable>
.PT2
<opn>\::= <par> | <par> ← <form>
.BOXB
.END
.APART
.GROUP;

.BEGIN TURN OFF "←";
.NL;
%21.%*##The formal parameters are  bound to the actual parameters from
left to right  as usual.
.NL
%22.%*##There must be an actual parameter for each required parameter, and
if there is no excess collector there may not be more actual parameters than
formals. (There may be fewer if we have optionals.)
.NL
%23.%*##If a <variable> in a formal parameter is preceded by a "%9`%*", then
the corresponding actual parameter is %6not%* evaluated. This is implements
the
%3quote%1-ing %3read%1 macro.
.NL
%24.%*##If we exhaust the   actual parameters while binding the optionals,
we   look at the remaining formal optionals.
If a formal parameter is simply a <par> then we bind it to %3(#)%*; if a formal is
%9`%1<variable>#←#<form> then we bind the <variable> to the <form>. 
.begin indent 4,4
If the formal is
<variable>#←#<form>, we bind <variable> to the value of <form>, where the
evaluation is to take place %6after%1 the required parameters have been bound.
.end
.NL
%25.%*##Finally, the excess collector is bound to a list of any remaining
actual parameters: if <par> is <variable> then 
using the calling environment, form a list
of the values of the remaining arguments; 
if <par> is %9`%1<variable>, bind <variable> to the
actual list. If there is no excess, bind to %3NIL%*.
.boxb
.END
.APART

.BEGIN TURN OFF "←";
We will also extend %3prog%*-variables slightly, allowing 
them to be initialized explicitly. If a %3prog%*-variable is atomic,
intialize it to %3(#)%*, as usual. If it is of the form <variable>#←#<form>
then initialize it to the value of the <form>.
.END
.END

.BEGIN TURN OFF "←";turn on "\"; tabs 14,24;
Here are some examples:
.PT2
.nl
1.##In the initialization of %3length%* on {yon(P45)}, we could write:
.BEGIN CENTER;turn off "←";
.pt2;pt2
%3...#prog[[l#←#x;#c#←#0]#...%*
.pt2;pt2
.END
.NL
2.##%3list%* could now be defined as: %3λ[[%1"excess"%* x]x]%*.
.pt18
.BEGIN NOFILL;
.group
.fp
3.##Consider the following definition:
.BOXA
\%3baz <= λ[\[x; %9`%*y;%1"optional"%* z; u ← 0; %1"excess"%* v]
\\print[x];
\\print[y];
\\print[z];
\\print[u];
\\print[v] ]
.BOXB
.APART
.GROUP
.FP
%1Then a call of:
.PT2
.BEGIN TABIT1(7);
%3eval[\(BAZ 2 (CAR (QUOTE (X Y))) 4 5 6 7 (CAR (QUOTE (A . B))));
\NIL]%1 
.END
.PT2
.FP
.SELECT 1;
would print:%3 \\2  
\\(CAR(QUOTE (X Y)))
\\4
\\5 
\\(6 7 A)%*
.FP
and return value: %3(6 7 A)%*.
.APART
.PT2
.GROUP
.FP
Similarly, defining:
.BOXA
\%3fii <= λ[\[x;y;%1"optional"%* z; u ← 0; %1"excess"%3 v]
\\print[x];
\\print[y];
\\print[z];
\\print[u];
\\print[v]] 
.BOXB
.BEGIN CENTERit;
.FP
%1and calling: ←%3eval[(FII 2 (CAR (QUOTE (X Y)));NIL]%* 
.END
.PT2
.FP
.SELECT 1;
prints:%3\\2 
\\X 
\\NIL 
\\0 
\\NIL%*
.END
.END
.PT2
.CENT(Problem);
.FP
Design simple S-expr representations of these proposed constructs.
Make the necessary extensions to %3eval%*.
.SS(Pretty-printing,,P226:)
.FP
This project expands on the basic notion of "pretty-printing" which
was introduced on {yon(P245)}.⊗↓Pretty printers are called
"grinders" at MIT.←  This section presents
several considerations involved in designing  such a pretty
printer. Take these suggestions and
develop a suitable program based on the suggestions and your experience
with your locally available pretty printer.
In  ⊗↑[Gol#73]↑ several pretty printing formats are discussed.
.GROUP;
.BOXA
.FP
I. %2Linear format%1: The minimal acceptable output format is that produced by %3print%1.
Acceptability is judged by whether that output can be read back into the
machine and have a structure %3equal%1 the the structure printed out.⊗↓We
must hedge that a bit, since %3gensym%1 atoms are not  placed on the
object list. Also structure made by %3rplaca%1 or %3rplacd%1 may not
be re-readable.← 
.APART
.GROUP;
.BOXA
.FP
II. %2Standard format%1: Given a list %3(%7a b c %1...%7 d%3)%1 the standard format
will assume that we are trying to print a function application and will produce:
.BEGIN GROUP;TABIT2(20,24);
.PT2
\%3(%7a\b
\\c
\\ %1. . .%7
\\d%3)
.BOXA
.END
.FP
Thus %3(FOO (CAR (CONS (QUOTE A) B)) (G (H A) 4))%1 would produce:
.PT2
.BEGIN GROUP;TABS 20,27,30,43;NOFILL;TURN ON "\";
.PT2
\%3(FOO\(CAR (CONS\(QUOTE A)
\\\\B))
\\(G\(H A)
\\\4))
.END
.PT2;
.FP
Note that the "standard format" is recursively applied, and thus 
may become too wide for the output device. It that case we can resort to the 
following format.
.APART
.GROUP;
.BOXA
.FP
III. %2Miser format%1: Write a list %3(%7a b c %1...%7 d%3)%1 as:
.BEGIN GROUP;TABIT2(20,22);
.PT2
\%3(%7a
\ b
\ c
\  %1. . .%7
\ d%3)
.PT2
.END
.FP
Again, the recursive application of this format can overflow the output
width. In that case we may have to resort to  "linear format".
.APART;
.GROUP;

Typical pretty printers also recognize certain LISP constructs
and "grind" them differently. That is, we build some semantic knowledge into the
grinder. Block format is useful in many of these contexts.
.BOXA
.FP
IV. %2Block format%1: A list %3(%7a%41%1#...#%7a%4i-1%1,#...#%7a%4n%3)%1
has  the block format:
.BEGIN TABIT2(20,21);
.PT2
\%3(\%7a%41%1#...#%7a%4i-1%1
\\%7a%4i%1#...#%7a%4n%3)%1
.PT2
.END
.FP
For  example, the list representation of a %3prog%1 might be "ground"
with its %3prog%1 variables in block format and special indenting
would be used
in the %3prog%1#body to emphasize the label and statement structure.
The representation of %3length%1 given on {yon(P250)} illustrates
the special format for %3prog%1s, though the %3prog%1#variable list is
not sufficently long to require block format.
.APART
.GROUP;

Another list format which is treated specially is the representation of
a λ-expression. 
.BEGIN GROUP;TABIT2(15,28);
.BOXA
\%3(LAMBDA\%1<λ-list ground in block format>
.PT2
\\<body ground as a block>%3)
.BOXA
.END
The example on {yon(P250)} also illistrates this.
This format will allow multiple-bodied λ-expressions.
For example:
.BEGIN SELECT 3; NOFILL;TURN ON "\";TABS 15,28,37
.PT2
\(LAMBDA\(X Y Z)
\\(CONS\X 
\\\(QUOTE A))
\\(H 1 2))
.PT2
.END
.APART
.FP
Notice that we decided to write %3(H 1 2)%1 in linear format
rather than standard format; somehow it "looks better". Personal
taste plays a  strong role in pretty printing, so several
grinders give  the users the ability to  describe their own
formats. We will see a similar, but more general device
in {yonss(P105)}.  Another possibility for user extension
lies with our property list evaluator of {yonss(P237)}.
Part of the definition of the various  LISP constructs would
allow the specification of output conventions for instances
of those constructs;  thus besides specifying evaluation properties
for %3LAMBDA%1, %3PROG%1, and %3COND%1, we would also  the
grinding routines for outputting instances of those constructs.

.GROUP;
Since lists beginning with %3COND%1 are representations of
conditional expressions they too are handled specially
by the grinding routines.

.BEGIN TABIT2(15,24);
.BOXA
\%3(COND%1\<grind clause%41%1>
.PT2
\\  . . .
.PT2
\\<grind clause%4n%1>%3)
.BOXB
.END
.APART
.FP
These selected formats should give a reasonable idea of the techniques available
for pretty printers. More techniques can be extracted from your local grinder.

.GROUP;
Your pretty printer may assume the existence of %3patom%1, %3print%1, and
%3terpri%1 of {yonss(P13)}; and you may assume the existence of
the usual class of arithmetic operations. In addition, the following
 primitives may be used:
.BOXA
.BEGIN def;GROUP;
%21.%1##%3linelength%1: If %3linelength[#]%1 is evaluated,
  the value returned is the number of characters allowed on a
line of the current output device. If %3linelength%1 is called with
a numeric argument, then the line length of the  current
output device is set to that
number.
.END
.APART
.BOXA
.BEGIN def;GROUP;
%22.%1##%3chrct%1: This is a nullary function, and returns
a number representing the number of character positions remaining on the current
line. For example, just after %3terpri[]%1 has been executed
.BEGIN NOFILL; indent 6,6
%3chrct[]#=#linelength[]%1
and %3prog%42%3[patom[ABC];#difference[linelength[];chrct[]]]#=#3%1 
.END
.END
.BOXA
.BEGIN def;GROUP;
%23.%1##%3flatsize%1:
A simple count of the
atoms and special characters in an expression won't give an accurate
picture of the requirements for printing an expression.
Special characters take one character position, but
literal atoms and numbers  may require more. 
To determine whether or not a special format can be used on an expression
requires knowledge of its character count. The number of characters
in the atom %3x%1 is given by %3flatsize[x]%1; for example,
%3flatsize[ABCD]%1 is %34%1. Actually %3flatsize%1 is defined
for non-atomic  arguments, giving the number of character positions
required to %3print%1 its argument. Thus, %3flatsize[(A.B)]%1
is %37%1 rather than %35%1 since %3print%1 will surround the
dot with spaces.
.END
.REQUIRE "NOTES.SDP" SOURCE_FILE;